package com.qf.springbootopenapi.service.impl;

import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qf.springbootopenapi.dao.UserDao;
import com.qf.springbootopenapi.entity.User;
import com.qf.springbootopenapi.service.UserService;
import com.qf.springbootopenapi.utils.Constants;
import com.qf.springbootopenapi.vo.ResultVo;
import com.qf.springbootopenapi.vo.TableVo;
import com.qf.springbootopenapi.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpSession;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;


@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {
    
    @Autowired
    private UserDao userDao;
    
    @Override
    public ResultVo login(String username, String password, HttpSession session) {
        
        log.debug("UserService查询用户收到的参数为username={},password={}", username, password);
    
        User user = userDao.getUserByUsername(username);
        
        if (user.getPassword().equals(DigestUtil.md5Hex(password))){
            session.setAttribute(Constants.USER_SESSION_KEY, user);
            return new ResultVo(Constants.SUCCESS_CODE, "登陆成功！");
        } else {
            return new ResultVo(Constants.FAIL_CODE, "登陆失败！");
        }
    }
    
    
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public User getUserByUsername(String username) {
        log.debug("UserService查询用户收到的参数为username={}", username);
        
        return userDao.getUserByUsername(username);
        
    }
    
    
    //注意：在service层方法中，不要 try...catch... 避免把异常捕获后，@Transactional就不会回滚了
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultVo createUser(UserVo userVo, String realPath) throws IOException {
        
        log.debug("UserService收到的参数为userVo={}", userVo);
        
        
        //生成一个随机文件名
        String uuid = UUID.randomUUID().toString();
        
        //文件扩展名的获取
        String extension = FilenameUtils.getExtension(userVo.getHeadPortrait().getOriginalFilename());
        
        String filePathAndFileName = realPath + File.separator + uuid + "." + extension;
        
        String fileName = uuid + "." + extension;
        
        userVo.getHeadPortrait().transferTo(new File(filePathAndFileName));
        
        User user = new User();
        
        BeanUtils.copyProperties(userVo, user);
        
        user.setRegistTime(new Date());
        user.setHeadPortrait(fileName);
        user.setName(userVo.getUsername());
        
        //处理密码加密
        String md5Password = DigestUtil.md5Hex(userVo.getPassword());
        user.setPassword(md5Password);
        
        log.debug("保存的用户信息为：user={}", user);
        
        System.out.println(user);
        
        Integer integer = userDao.insertUser(user);
        
        if (integer == 1) {
            return new ResultVo(Constants.SUCCESS_CODE, "用户注册成功！");
        } else {
            return new ResultVo(Constants.FAIL_CODE, "用户注册失败！");
        }
    }
    
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public TableVo<User> getAllUserByPage(Integer page, Integer limit) {
        
        //查询user表总条数
        Integer count = userDao.selectCount();
        
        //查询当前页用户数据
        Integer start = (page - 1) * limit; //计算分页的起始行号
        List<User> users = userDao.selectUserByPage(start, limit);
    
        TableVo<User> userTableVo = new TableVo<>();
        
        userTableVo.setCode(0);
        userTableVo.setMsg("");
        userTableVo.setData(users);
        userTableVo.setCount(count);
    
        return userTableVo;
    }
    
    
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public User restoreUser(String username, String md5Password) {
        log.debug("UserService查询用户收到的参数为username={},password={}", username, md5Password);
    
        User user = userDao.getUserByUsername(username);
        
        if (!Optional.ofNullable(user).isPresent()){
            return null;
        }
    
        if (user.getPassword().equals(md5Password)){
            return user;
        } else {
            return null;
        }
    }
    
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public TableVo<User> getUserByPageHelper(Integer page, Integer limit) {
        PageHelper.startPage(page, limit);
        List<User> allUser = userDao.getAllUser();
        
        PageInfo<User> userPageInfo = new PageInfo<>(allUser);
    
        long total = userPageInfo.getTotal();
    
        return TableVo.ok((int)total, allUser);
    }
    
    
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultVo addUser(User user) {
        
        user.setRegistTime(new Date());
        
        //处理密码加密
        user.setPassword(DigestUtil.md5Hex(user.getPassword()));
    
        log.debug("保存的用户信息为：user={}", user);
    
        System.out.println(user);
    
        Integer integer = userDao.insertUser(user);
    
        if (integer == 1) {
            return new ResultVo(Constants.SUCCESS_CODE, "用户添加成功！");
        } else {
            return new ResultVo(Constants.FAIL_CODE, "用户添加失败！");
        }
    }
    
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultVo updateUser(User user) {
    
        User originalUser = userDao.selectUserById(user.getId());
    
        String originalPassword = originalUser.getPassword();
    
        if (!user.getPassword().equals(originalPassword)){
            //处理密码加密
            user.setPassword(DigestUtil.md5Hex(user.getPassword()));
        }
        
    
        log.debug("保存的用户信息为：user={}", user);
    
        Integer integer = userDao.updateUserById(user);
    
        if (integer == 1) {
            return new ResultVo(Constants.SUCCESS_CODE, "用户添加成功！");
        } else {
            return new ResultVo(Constants.FAIL_CODE, "用户添加失败！");
        }
    }
    
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultVo delUser(Integer[] ids) {
    
        Integer integer = userDao.delUserByIds(ids);
    
        if (integer != 0) {
            return new ResultVo(Constants.SUCCESS_CODE, "用户添加成功！");
        } else {
            return new ResultVo(Constants.FAIL_CODE, "用户添加失败！");
        }
    }
    
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public TableVo<User> getUsersByCondition(Integer page, Integer limit, UserVo userVo) {
        
        PageHelper.startPage(page, limit);
        List<User> data = userDao.getUsersByCondition(userVo);
    
        long total = new PageInfo<>(data).getTotal();
        
        return TableVo.ok((int) total, data);
    }
    
    @Override
    public void getCsvFile(String filenameAndPath) throws IOException {
        List<User> allUser = userDao.getAllUser();
    
        List<String> stringUsers = allUser.stream().map(User::toCSVString).collect(Collectors.toList());
    
        BufferedWriter bw = new BufferedWriter(new FileWriter(filenameAndPath));
    
        for (String stringUser : stringUsers) {
            bw.write(stringUser);
            bw.newLine();
        }
    
        bw.close();
    }
    
    @Override
    public void deleteHeadPortrait() {
    
        File filePath = new File(System.getProperty("user.dir") + File.separator + "Upload");
        File[] files = filePath.listFiles();
        List<String> fileString = Arrays.stream(files).map(File::getName).collect(Collectors.toList());
    
        for (String s : fileString) {
            if (userDao.selectHeadPortrait(s) == null){
                File file = new File(filePath + File.separator + s);
                file.delete();
            }
        }
    
    }
}
